home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene Storm
/
Scene Storm - Volume 1.iso
/
coding
/
c
/
vbcc
/
ic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-23
|
32KB
|
927 lines
#include "vbc.h"
struct IC *first_ic=0,*last_ic=0;
int float_used;
int do_arith(np,struct IC *,np,struct obj *);
void add_IC(struct IC *new)
/* fuegt ein IC ein */
{
int code;
if(!new) return;
if(nocode) {free(new);return;}
new->next=0;
new->q1.am=new->q2.am=new->z.am=0;
code=new->code;
if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
if(DEBUG&64) pric2(stdout,new);
if(new->q1.flags&VAR){
if(!new->q1.v) ierror(0);
new->q1.v->flags|=USEDASSOURCE;
if(code==ADDRESS||(new->q1.flags&VARADR)) new->q1.v->flags|=USEDASADR;
new->q1.v->priority+=currentpri;
}
if(new->q2.flags&VAR){
if(!new->q2.v) ierror(0);
new->q2.v->flags|=USEDASSOURCE;
if(code==ADDRESS||(new->q2.flags&VARADR)) new->q2.v->flags|=USEDASADR;
new->q2.v->priority+=currentpri;
}
if(new->z.flags&VAR){
if(!new->z.v) ierror(0);
if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST;
new->z.v->priority+=currentpri;
}
if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
/* entfernt Spruenge zu direkt folgenden Labels */
struct IC *p=last_ic;
while(p){
if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
remove_IC(p);
if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
}else{
if(p->code!=LABEL) break;
}
p=p->prev;
}
}
if(last_ic){
/* if(c_flags_val[0].l&2){*/
if(code==ASSIGN){
if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg&&last_ic->code!=CALL){
if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
/* verbindet op a,b->reg,move reg->c zu op a,b->c */
/* hier fehlt aber noch Registerfreigabe */
last_ic->z=new->z;
if(DEBUG&1) printf("move and op combined\n");
if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
free_reg(new->q1.reg);
free(new);
return;
}
}
}
}
if(last_ic->code==BRA){
if(code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
/* loescht alles nach bra bis ein Label kommt */
/* momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
free(new);
if(DEBUG&1) printf("Unreachable Statement deleted\n");
return;
}
if(last_ic->prev&&code==LABEL){
/* ersetzt bcc l1;bra l2;l1 durch b!cc l2 */
if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
if(last_ic->prev->code&1) last_ic->prev->code--;
else last_ic->prev->code++;
last_ic->prev->typf=last_ic->typf;
last_ic=last_ic->prev;
free(last_ic->next);
last_ic->next=new;new->prev=last_ic;
last_ic=new;
return;
}
}
}
/* }*/
new->prev=last_ic;
last_ic->next=new;
last_ic=new;
}else{
last_ic=new;first_ic=new;new->prev=0;
}
/* Merken, on Fliesskomma benutzt wurde */
if(code!=LABEL&&(code<BEQ||code>BRA))
if((new->typf&15)==FLOAT||(new->typf&15)==DOUBLE) float_used=1;
if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
free_reg(new->q1.reg);
if((new->q2.flags&SCRATCH)&&(new->q2.reg!=new->z.reg||!(new->z.flags®)))
free_reg(new->q2.reg);
}
void free_IC(struct IC *p)
/* Gibt IC-Liste inkl. Typen frei */
{
struct IC *merk;
while(p){
if(!(c_flags_val[0].l&128)){
if(p->q1.am||p->q2.am||p->z.am)
{p->q1.am=p->q2.am=p->z.am=0;ierror(0);}
}else{
if(p->q1.am) free(p->q1.am);
if(p->q2.am) free(p->q2.am);
if(p->z.am) free(p->z.am);
}
merk=p->next;
free(p);
p=merk;
}
}
void gen_IC(np p,int ltrue,int lfalse)
/* Erzeugt eine IC-Liste aus einer expression */
{
struct IC *new;
if(!p) return;
if(p->flags==STRING){
/* hier fehlt noch die Verwaltung der String-Inhalte */
p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,(struct const_list *)p->identifier);
p->o.v->flags|=DEFINED;
p->o.flags=VAR;
p->o.reg=0;
p->o.val=p->val;
return;
}
if(p->flags==IDENTIFIER){
p->o.v=find_var(p->identifier,0);
p->o.flags=VAR;
p->o.reg=0;
p->o.val=p->val;
return;
}
if(p->flags==CEXPR||p->flags==PCEXPR){
if(p->left){
if(p->left->flags==POSTINC) p->left->flags=PREINC;
if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
gen_IC(p->left,0,0);
if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
}
if(p->right){
if(p->right->flags==POSTINC) p->right->flags=PREINC;
if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
gen_IC(p->right,0,0);
if(p->right->o.flags&SCRATCH) free_reg(p->right->o.reg);
}
p->o.flags=KONST;
p->o.val=p->val;
p->o.reg=0;
return;
}
if(p->flags==KOMMA){
if(p->left->sidefx){
gen_IC(p->left,0,0);
if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
} else error(129);
gen_IC(p->right,0,0);
p->o=p->right->o;
return;
}
if(p->flags==CAST){
gen_IC(p->left,0,0);
convert(p->left,p->ntyp->flags&31);
p->o=p->left->o;
return;
}
if(p->flags==FIRSTELEMENT){
gen_IC(p->left,0,0);
p->o=p->left->o;
return;
}
new=(struct IC *)mymalloc(ICS);
new->typf=p->ntyp->flags&31;
new->q1.reg=new->q2.reg=new->z.reg=0;
new->q1.flags=new->q2.flags=new->z.flags=0;
if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
do_arith(p,new,0,0);
return;
}
if(p->flags==CONTENT){
gen_IC(p->left,0,0);
if(p->left->o.flags&VARADR){
free(new);
p->o=p->left->o;
p->o.flags&=~VARADR;
return;
}
if(!(p->left->o.flags&DREFOBJ)){
free(new);
p->o=p->left->o;
p->o.flags|=DREFOBJ;
return;
}
if(p->left->o.flags&SCRATCH){
new->z=p->left->o;
new->z.flags&=~DREFOBJ;
}else{
/* hier muss man noch was aender, da das so nicht funktioniert */
get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
}
new->code=ASSIGN;new->typf=POINTER;
new->q1=p->left->o;
new->q2.reg=sizetab[POINTER];
add_IC(new);
p->o=new->z;
p->o.flags|=DREFOBJ;
return;
}
if(p->flags==ASSIGN){
new->code=ASSIGN;
gen_IC(p->right,0,0);
gen_IC(p->left,0,0);
convert(p->right,p->ntyp->flags&31);
new->q1=p->right->o;
new->z=p->left->o;
new->q2.reg=szof(p->left->ntyp);
add_IC(new);
p->o=new->z;
return;
}
if(p->flags==ASSIGNADD){
/* das hier ist nicht besonders schoen */
struct obj o;struct IC *n;int f;
if(p->right->right==0){
/* sowas wie a+=0 wurde wegoptimiert */
free(new);
p->o=p->left->o;
return;
}
f=do_arith(p->right,new,p->left,&o);
if(!f) {ierror(0);return;}
if(f>1) {ierror(0);return;}
if(!nocode&&(o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg]){
/* ueberfluessiges FREEREG entfernen */
n=last_ic;
while(n){
if(n->code==FREEREG&&n->q1.reg==o.reg){
remove_IC(n);if(!nocode) regs[o.reg]=1;
break;
}
n=n->prev;
}
}
convert(p->right,p->ntyp->flags&31);
new=(struct IC *)mymalloc(ICS);
new->typf=p->ntyp->flags&31;
new->q2.flags=0;
new->code=ASSIGN;
new->q1=p->right->o;
new->z=o;
new->q2.reg=szof(p->left->ntyp);
add_IC(new);
p->o=new->z;
return;
}
if(p->flags==MINUS||p->flags==KOMPLEMENT){
new->code=p->flags;
gen_IC(p->left,0,0);
convert(p->left,p->ntyp->flags);
if(regok(p->left->o.reg,p->ntyp->flags,0)&&(p->left->o.flags&SCRATCH)){
new->z=p->left->o;
new->z.flags&=~DREFOBJ;
}else{
get_scratch(&new->z,p->left->ntyp->flags,0);
}
new->q1=p->left->o;
add_IC(new);
p->o=new->z;
return;
}
if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
new->code=ADDRESS;
new->typf=p->left->ntyp->flags&31;
gen_IC(p->left,0,0);
if(p->left->o.flags&VAR) p->left->o.v->flags|=USEDASSOURCE|USEDASDEST;
if(p->left->o.flags&DREFOBJ){
free(new);
p->o=p->left->o;
p->o.flags&=~DREFOBJ;
return;
}
if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
&&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
free(new);
p->o=p->left->o;
p->o.flags|=VARADR;
return;
}
new->q1=p->left->o;
get_scratch(&new->z,POINTER,p->ntyp->next->flags);
add_IC(new);
p->o=new->z;
return;
}
if(p->flags==LAND||p->flags==LOR){
int l1,l2,l3,l4;
/* printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
l1=++label;if(!ltrue) {l2=++label;l3=++label;l4=++label;}
if(!ltrue){if(p->flags==LAND) gen_IC(p->left,l1,l3);
else gen_IC(p->left,l3,l1);
}else {if(p->flags==LAND) gen_IC(p->left,l1,lfalse);
else gen_IC(p->left,ltrue,l1);
}
if(p->left->o.flags!=0){
new->code=TEST;
new->q2.flags=new->z.flags=0;
new->typf=p->left->ntyp->flags&31;
new->q1=p->left->o;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
if(p->flags==LAND) new->code=BEQ; else new->code=BNE;
if(!ltrue) new->typf=l3;
else{if(p->flags==LAND) new->typf=lfalse; else new->typf=ltrue;}
add_IC(new);
}
gen_label(l1);
if(!ltrue){if(p->flags==LAND) gen_IC(p->right,l2,l3);
else gen_IC(p->right,l3,l2);
}else gen_IC(p->right,ltrue,lfalse);
if(p->right->o.flags!=0){
new=(struct IC *)mymalloc(ICS);
new->code=TEST;
new->q2.flags=new->z.flags=0;
new->typf=p->right->ntyp->flags&31;
new->q1=p->right->o;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
if(p->flags==LAND) new->code=BEQ; else new->code=BNE;
if(!ltrue) new->typf=l3;
else{if(p->flags==LAND) new->typf=lfalse; else new->typf=ltrue;}
add_IC(new);
}
if(!ltrue){
gen_label(l2);
if(p->flags==LAND) p->o=gen_cond(0,l3,l4); else p->o=gen_cond(1,l3,l4);
}else{
new=(struct IC *)mymalloc(ICS);
new->code=BRA;
if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
add_IC(new);
}
if(ltrue) p->o.flags=0;
return;
}
if(p->flags==NEGATION){
int l1,l2,l3;
if(!ltrue) {l1=++label;l2=++label;l3=++label;}
if(ltrue) gen_IC(p->left,lfalse,ltrue); else gen_IC(p->left,l1,l3);
if(!p->left->o.flags) {free(new);p->o.flags=0;
}else{
new->code=TEST;
new->q2.flags=new->z.flags=0;
new->typf=p->left->ntyp->flags&31;
new->q1=p->left->o;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
new->code=BNE;
if(!ltrue) new->typf=l1; else new->typf=lfalse;
add_IC(new);
}
if(ltrue){
new=(struct IC *)mymalloc(ICS);
new->code=BRA;
if(!ltrue) new->typf=l2; else new->typf=ltrue;
add_IC(new);
p->o.flags=0;
}else{
gen_label(l3);
p->o=gen_cond(0,l1,l2);
}
return;
}
if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
int l1,l2,l3,tl,tr,swapped;
if(!ltrue) {l1=++label;l2=++label;l3=++label;}
if(p->left->flags==CEXPR){
/* Konstanten nach rechts */
np merk;merk=p->left;p->left=p->right;p->right=merk;
swapped=1;
}else swapped=0;
new->code=COMPARE;
tl=p->left->ntyp->flags&31;tr=p->right->ntyp->flags&31;
if(p->right->flags==CEXPR&&(tr&15)<FLOAT&&(tl&15)<FLOAT){
zlong null;int negativ;
eval_constn(p->right);
null=l2zl(0L);
if(zlleq(vlong,0)) negativ=1; else negativ=0;
if(tr&UNSIGNED) negativ=0;
if((!negativ||zlleq(t_min[tl],vlong))&&(negativ||zulleq(vulong,t_max[tl]))){
convert(p->right,tl);
tr=tl;
}
}
if(arith(tl)&&tl!=tr){
struct Typ *t;
t=arith_typ(p->left->ntyp,p->right->ntyp);
new->typf=t->flags&31;
freetyp(t);
}else{
new->typf=p->left->ntyp->flags&31;
}
gen_IC(p->left,0,0);
convert(p->left,new->typf);
gen_IC(p->right,0,0);
convert(p->right,new->typf);
new->q1=p->left->o;
new->q2=p->right->o;
new->z.flags=0;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
if(p->flags==EQUAL) new->code=BEQ;
if(p->flags==INEQUAL) new->code=BNE;
if(p->flags==LESS) {if(swapped) new->code =BGT; else new->code=BLT;}
if(p->flags==LESSEQ){if(swapped) new->code=BGE; else new->code=BLE;}
if(p->flags==GREATER){if(swapped) new->code=BLT; else new->code=BGT;}
if(p->flags==GREATEREQ){if(swapped) new->code=BLE; else new->code=BGE;}
if(ltrue) new->typf=ltrue; else new->typf=l1;
add_IC(new);
if(ltrue){
new=(struct IC *)mymalloc(ICS);
new->code=BRA;
new->typf=lfalse;
add_IC(new);
p->o.flags=0;
}else{
gen_label(l3);
p->o=gen_cond(1,l1,l2);
}
return;
}
if(p->flags==CALL){
int r,regused,sz;
function_calls+=currentpri;
gen_IC(p->left,0,0);
if(!(p->left->o.flags&DREFOBJ)){
free(new);
p->o=p->left->o;
if(p->o.flags&VARADR) p->o.flags&=~VARADR;
else p->o.flags|=DREFOBJ;
}else{
if(p->left->o.flags&VARADR){
free(new);
p->o=p->left->o;
p->o.flags&=~VARADR;
}else{
if(p->left->o.flags&SCRATCH){
new->z=p->left->o;
new->z.flags&=~DREFOBJ;
}else{
/* das hier funktioniert vermutlich auch nicht */
get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
}
new->code=ASSIGN;new->typf=POINTER;
new->q1=p->left->o;
new->q2.reg=sizetab[POINTER];
new->q2.flags=0;
add_IC(new);
p->o=new->z;
p->o.flags|=DREFOBJ;
}
}
/* p->left->o.flags-=DREFOBJ|VARADR; Was sollte das?? */
r=freturn(p->ntyp);
if(!r){
struct Typ *t=mymalloc(TYPS);
t->flags=POINTER;t->next=p->ntyp;
r=freturn(t);
free(t);
}
if(!r) ierror(0);
regused=regs[r];
new=(struct IC *)mymalloc(ICS);
new->code=SAVEREGS;
new->typf=0;
if((p->o.flags&(REG|SCRATCH))==(REG|SCRATCH)) new->q1.reg=p->o.reg;
else new->q1.reg=0;
new->q1.flags=new->q2.flags=new->z.flags=0;
add_IC(new);
sz=push_args(p->alist,p->left->ntyp->next->exact,0);
if(!regused){
if(!nocode) regs[r]=1;
new=(struct IC *)mymalloc(ICS);
new->code=ALLOCREG;
new->typf=0;
new->q1.flags=REG;
new->q1.reg=r;
new->q2.flags=new->z.flags=0;
add_IC(new);regused=0;
}
new=(struct IC *)mymalloc(ICS);
new->code=CALL;new->typf=FUNKT;
new->q1=p->o;new->q2.flags=0;
new->q2.reg=sz;
new->z.reg=r;
/* hier noch Returnregister retten etc. */
new->z.flags=REG;
if(!regused) new->z.flags|=SCRATCH;
add_IC(new);
p->o=new->z;
if(!freturn(p->ntyp)) p->o.flags|=DREFOBJ;
if(regused){
if((p->ntyp->flags&15)!=VOID){
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->typf=p->ntyp->flags&31;
new->q1=p->o;
new->q2.reg=szof(p->ntyp);
new->q2.flags=0;
get_scratch(&new->z,p->ntyp->flags&31,0);
add_IC(new);
p->o=new->z;
}
}
new=(struct IC *)mymalloc(ICS);
new->code=RESTOREREGS;
new->typf=0;
if(p->o.flags®) new->q1.reg=p->o.reg; else new->q1.reg=0;
new->q1.flags=new->q2.flags=new->z.flags=0;
add_IC(new);
return;
}
if(p->flags>=PREINC&&p->flags<=POSTDEC){
struct obj o;
gen_IC(p->left,0,0);
if(p->flags==POSTINC||p->flags==POSTDEC){
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->typf=p->ntyp->flags&31;
new->q2.reg=sizetab[p->ntyp->flags&15];
new->q1=p->left->o;
new->q1.flags&=~SCRATCH;
get_scratch(&new->z,p->left->ntyp->flags&31,0);
new->q2.flags=0;
add_IC(new);
o=new->z;
new=(struct IC *)mymalloc(ICS);
}else o=p->left->o;
if((p->left->ntyp->flags&15)==POINTER){
if(p->flags==PREINC||p->flags==POSTINC) new->code=ADDI2P; else new->code=SUBIFP;
vlong=l2zl((long)szof(p->left->ntyp->next));
new->q2.val.vint=zl2zi(vlong);
new->typf=INT;
new->q1=p->left->o;
new->z=p->left->o;
new->q2.flags=KONST;
add_IC(new);
}else{
if(p->flags==PREINC||p->flags==POSTINC) new->code=ADD; else new->code=SUB;
new->typf=p->ntyp->flags&31;
new->q1=p->left->o;
new->z=p->left->o;
new->q2.flags=KONST;
vlong=l2zl(1L);vulong=zl2zul(vlong);vdouble=zl2zd(vlong);
if(new->typf==CHAR) new->q2.val.vchar=zl2zc(vlong);
if(new->typf==SHORT) new->q2.val.vshort=zl2zs(vlong);
if(new->typf==INT) new->q2.val.vint=zl2zi(vlong);
if(new->typf==LONG) new->q2.val.vlong=vlong;
if(new->typf==(UNSIGNED|CHAR)) new->q2.val.vuchar=zul2zuc(vulong);
if(new->typf==(UNSIGNED|SHORT)) new->q2.val.vushort=zul2zus(vulong);
if(new->typf==(UNSIGNED|INT)) new->q2.val.vuint=zul2zui(vulong);
if(new->typf==(UNSIGNED|LONG)) new->q2.val.vulong=vulong;
if(new->typf==DOUBLE) new->q2.val.vdouble=vdouble;
if(new->typf==FLOAT) new->q2.val.vfloat=zd2zf(vdouble);
add_IC(new);
}
if(p->flags==POSTINC||p->flags==POSTDEC){
if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
}
p->o=o;
return;
}
if(p->flags==COND){
int ltrue,lfalse,lout;
ltrue=++label;lfalse=++label;lout=++label;
gen_IC(p->left,ltrue,lfalse);
if(!p->left->o.flags){
free(new);
}else{
if(p->left->flags!=CEXPR){
new->code=TEST;
new->typf=p->left->ntyp->flags&31;
new->q1=p->left->o;
new->q2.flags=new->z.flags=0;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
new->code=BEQ;
new->typf=lfalse;
add_IC(new);
}else{
eval_constn(p->left);
if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
gen_IC(p->right->right,0,0);
p->o=p->right->right->o;
}else{
gen_IC(p->right->left,0,0);
p->o=p->right->left->o;
}
return;
}
}
gen_label(ltrue);
gen_IC(p->right->left,0,0);
convert(p->right->left,p->ntyp->flags&31);
if(p->right->left->o.flags&SCRATCH){
p->o=p->right->left->o;
}else{
get_scratch(&p->o,p->ntyp->flags&31,0);
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->q1=p->right->left->o;
new->z=p->o;
new->q2.flags=0;
new->q2.reg=szof(p->ntyp);
new->typf=p->ntyp->flags&31;
add_IC(new);
p->o=new->z;
}
new=(struct IC *)mymalloc(ICS);
new->code=BRA;
new->typf=lout;
add_IC(new);
gen_label(lfalse);
gen_IC(p->right->right,0,0);
convert(p->right->right,p->ntyp->flags&31);
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->q1=p->right->right->o;
new->z=p->o;
new->q2.flags=0;
new->q2.reg=szof(p->ntyp);
new->typf=p->ntyp->flags&31;
add_IC(new);
gen_label(lout);
return;
}
printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
ierror(0);
free(new);
p->o.flags=0;
}
int push_args(struct argument_list *al,struct struct_declaration *sd,int n)
/* Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge */
/* auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird */
/* nach double konvertiert, falls kein Prototype da ist. Ausserdem werden */
/* alle Argumente in ihrer Groesse aligned. Das ist evtl. nicht fuer jede */
/* CPU ausreichend. Hier muss evtl. noch etwas getan werden. */
{
int of,t,sz;struct IC *new;
if(!al) return(0);
if(al->next) of=push_args(al->next,sd,n+1); else of=0;
if(!al->arg) {ierror(0);return(of);}
if(!sd) {ierror(0);return(of);}
gen_IC(al->arg,0,0);
if(n<sd->count){t=sd->sl[n].styp->flags&15;sz=szof(sd->sl[n].styp);}
else {t=al->arg->ntyp->flags&15;sz=szof(al->arg->ntyp);}
if(t>=CHAR&&t<=LONG) {t=int_erw(t);sz=sizetab[t&15];}
if(t==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];}
convert(al->arg,t&31);
new=(struct IC *)mymalloc(ICS);
new->code=PUSH;
new->typf=t;
new->q1=al->arg->o;
new->q2.flags=new->z.flags=0;
new->q2.reg=((sz+maxalign-1)/maxalign)*maxalign;
add_IC(new);
return(of+sz);
}
void convert(np p,int f)
/* konvertiert das Objekt in p->o in bestimmten Typ */
{
struct IC *new;
if((f&15)==VOID||(p->ntyp->flags&31)==f) return;
if(p->flags==CEXPR||p->flags==PCEXPR){
eval_constn(p);
p->ntyp->flags=f;
insert_const(p);
p->o.val=p->val;
return;
}
if(!must_convert(p,f)) return;
new=(struct IC *)mymalloc(ICS);
new->q1=p->o;
new->q2.flags=0;
new->code=CONVCHAR+(p->ntyp->flags&15)-CHAR;
if(p->ntyp->flags&UNSIGNED) new->code+=8;
new->typf=f;
if(!regok(p->o.reg,f,0)||!(p->o.flags&SCRATCH)){
get_scratch(&new->z,f,0);
add_IC(new);
}else{
new->z=p->o;new->z.flags&=~DREFOBJ;
add_IC(new);
}
p->o=new->z;
}
int allocreg(int f,int mode)
/* Fordert Register fuer Typ f an */
/* evtl. maschinenabhaengig, aber hier fehlt noch viel */
/* z.B. Eintragen eines IC */
{
int i;struct IC *new;
if(nocode) return(1);
for(i=1;i<=MAXR;i++){
if(!regs[i]&®ok(i,f,mode)){
if(DEBUG&16) printf("alocated %s\n",regnames[i]);
regs[i]=1;regused[i]++;
new=(struct IC *)mymalloc(ICS);
new->code=ALLOCREG;
new->typf=0;
new->q1.flags=REG;
new->q1.reg=i;
new->q2.flags=new->z.flags=0;
add_IC(new);
return(i);}
}
if(DEBUG&1) printf(">%sCouldn't allocate register for type %d\n",string,f);
return(0);
}
void free_reg(int r)
/* Gibt Register r frei */
/* Eintrag eines IC fehlt noch */
{
struct IC *new;
if(!r||nocode) return;
if(regs[r]==0) {printf("Register %s:\n",regnames[r]);ierror(0);}
if(DEBUG&16) printf("freed %s\n",regnames[r]);
new=(struct IC *)mymalloc(ICS);
new->code=FREEREG;
new->typf=0;
new->q1.flags=REG;
new->q1.reg=r;
new->q2.flags=new->z.flags=0;
add_IC(new);
regs[r]=0;
}
void gen_label(int l)
/* Erzeugt ein Label */
{
struct IC *new;
new=(struct IC *)mymalloc(ICS);
new->code=LABEL;
new->typf=l;
new->q1.flags=new->q2.flags=new->z.flags=0;
add_IC(new);
}
struct obj gen_cond(int m,int l1,int l2)
/* Generiert code, der 0 oder 1 in Register schreibt */
{
struct IC *new;
struct obj omerk;
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->typf=INT;
new->q1.flags=KONST;
new->q2.flags=0;
new->q2.reg=sizetab[INT];
if(!m) vlong=l2zl(1L); else vlong=l2zl(0L);
new->q1.val.vint=zl2zi(vlong);
get_scratch(&new->z,INT,0);
omerk=new->z;
add_IC(new);
new=(struct IC *)mymalloc(ICS);
new->code=BRA;
new->typf=l2;
add_IC(new);
gen_label(l1);
new=(struct IC *)mymalloc(ICS);
new->code=ASSIGN;
new->typf=INT;
new->q1.flags=KONST;
new->q2.flags=0;
new->q2.reg=sizetab[INT];
if(!m) vlong=l2zl(0L); else vlong=l2zl(1L);
new->q1.val.vint=zl2zi(vlong);
new->z=omerk;
/* new->z.reg=r;
new->z.flags=SCRATCH|REG;*/
add_IC(new);
gen_label(l2);
return(omerk);
}
void scratch_var(struct obj *o,int t)
/* liefert eine temporaere Variable */
/* nicht effizient, aber wer hat schon so wenig Register... */
{
struct Typ *nt=(struct Typ *)mymalloc(TYPS);
if((t&15)<CHAR||(t&15)>POINTER) ierror(0);
nt->flags=t&31;
if((t&15)==POINTER){
nt->next=(struct Typ *)mymalloc(TYPS);
nt->next->flags=VOID;
nt->next->next=0;
}else nt->next=0;
o->flags=SCRATCH|VAR;o->reg=0;
o->v=add_var(empty,nt,AUTO,0);
o->val.vlong=l2zl(0L);
}
void get_scratch(struct obj *o,int t1,int t2)
/* liefert ein Scratchregister oder eine Scratchvariable */
{
if(o->reg=allocreg(t1,t2)){
o->flags=SCRATCH|REG;
}else{
scratch_var(o,t1);
}
}
void remove_IC(struct IC *p)
/* entfernt IC p aus Liste */
{
if(p->prev) p->prev->next=p->next; else first_ic=p->next;
if(p->next) p->next->prev=p->prev; else last_ic=p->prev;
if(p->q1.am) free(p->q1.am);
if(p->q2.am) free(p->q2.am);
if(p->z.am) free(p->z.am);
free(p);
}
int do_arith(np p,struct IC *new,np dest,struct obj *o)
/* erzeugt IC new fuer einen arithmetischen Knoten und speichert das */
/* Resultat vom Unterknoten dest in o (fuer a op= b) */
/* liefert 0, wenn dest nicht gefunden */
{
int f=0;
new->code=p->flags;
if(new->code==PMULT) new->code=MULT;
gen_IC(p->left,0,0);
if(dest&&p->left==dest) {*o=p->left->o;f++;}
gen_IC(p->right,0,0);
if(dest&&p->right==dest) {*o=p->right->o;f++;}
if((p->left->ntyp->flags&15)==POINTER&&(p->right->ntyp->flags&15)==POINTER){
/* Subtrahieren zweier Pointer */
if(p->flags!=SUB) ierror(0);
new->typf=INT;
new->code=SUBPFP;
new->q1=p->left->o;
new->q2=p->right->o;
if(p->left->o.flags&SCRATCH&®ok(p->left->o.reg,INT,0)){
new->z=p->left->o;
new->z.flags&=~DREFOBJ;
}else{
if(USEQ2ASZ&&(p->right->o.flags&SCRATCH)&®ok(p->right->o.reg,INT,0)){
new->z=p->left->o;
new->z.flags&=(~DREFOBJ);
}else{
get_scratch(&new->z,INT,0);
}
}
add_IC(new);
p->o=new->z;
if(szof(p->left->ntyp->next)>1){
new=(struct IC *)mymalloc(ICS);
new->code=DIV;
new->q1=p->o;
new->q2.flags=KONST;
vlong=l2zl((long)szof(p->left->ntyp->next));
vint=zl2zi(vlong);
new->q2.val.vint=vint;
new->z=p->o;
new->typf=INT;
add_IC(new);
}
return(f);
}
if((p->flags==ADD||p->flags==SUB)&&(p->ntyp->flags&15)==POINTER){
/* Addieren und Subtrahieren eines Integers zu einem Pointer */
if(p->flags==ADD) new->code=ADDI2P; else new->code=SUBIFP;
new->typf=p->right->ntyp->flags&31;
new->q1=p->left->o;
/* kleinere Typen als MINADDI2P erst in diesen wandeln */
if((new->typf&15)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;}
new->q2=p->right->o;
if((p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&31)){
new->z=p->left->o;
new->z.flags&=(~DREFOBJ);
}else{
get_scratch(&new->z,POINTER,p->left->ntyp->next->flags&31);
}
add_IC(new);
p->o=new->z;
return(f);
}
convert(p->left,p->ntyp->flags&31);
convert(p->right,p->ntyp->flags&31);
new->q1=p->left->o;
new->q2=p->right->o;
new->typf=p->ntyp->flags&31;
if((new->q1.flags&SCRATCH)&®ok(new->q1.reg,p->ntyp->flags,0)){
new->z=new->q1;
new->z.flags&=~DREFOBJ;
}else{
if((new->q2.flags&SCRATCH)&®ok(new->q2.reg,p->ntyp->flags,0)){
if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
/* bei kommutativen Operatoren vertauschen */
new->z=new->q2;
new->q2=new->q1;
new->q1=new->z;
new->z.flags&=~DREFOBJ;
}else{
if(USEQ2ASZ){
new->z=new->q2;
new->z.flags&=~DREFOBJ;
}else{
get_scratch(&new->z,new->typf,0);
}
}
}else{
get_scratch(&new->z,new->typf,0);
}
}
add_IC(new);
p->o=new->z;
return(f);
}